package cn.gs.common.config;

import cn.gs.common.realm.AuthRealm;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.ShiroFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @author gs
 * @date 2020/1/9
 */
@Configuration
public class ShiroConfig {

    /*
      其实 最基本的配置 就三个
      1. 自定义的Realm()
      2.securityManager（），将 Realm() 注入其中
      3.过滤连  ShiroFilterFactoryBean ，securityManager作为入参传入
     */

    //配置过滤链
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager){
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        shiroFilterFactoryBean.setLoginUrl("/login");
        shiroFilterFactoryBean.setUnauthorizedUrl("/error/403");

        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
        filterChainDefinitionMap.put("/login", "anon");
        filterChainDefinitionMap.put("/gifCode", "anon");
        filterChainDefinitionMap.put("/css/**", "anon");
        filterChainDefinitionMap.put("/fonts/**", "anon");
        filterChainDefinitionMap.put("/img/**", "anon");
        filterChainDefinitionMap.put("/js/**", "anon");
        filterChainDefinitionMap.put("/lib/**", "anon");

        filterChainDefinitionMap.put("/**", "authc");

        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilterFactoryBean;
    }

    //获取对shiro bean生命周期的管理实例
    @Bean
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor(){
        return new LifecycleBeanPostProcessor();
    }

    @Bean
    public SecurityManager securityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();

        //securityManager.setSessionManager(sessionManager());
        // 不要每次都查一遍用户的权限
        //securityManager.setCacheManager(cacheManager());
        securityManager.setRealm(realm(hashedCredentialsMatcher()));
        return securityManager;
    }

    @Bean
    public Realm realm(HashedCredentialsMatcher hashedCredentialsMatcher) {
        AuthRealm realm = new AuthRealm();
        realm.setCredentialsMatcher(hashedCredentialsMatcher);
        return realm;
    }

    //如果我们希望 我们存入数据库的密码 是结果shiro 加盐加密的 （一般用shiro自己的类加盐加密，自己设置好存入数据库）
    // 那么登录的时候要为realm 注入这个 CredentialsMatcher 其配置 一定要和密码加盐加密的方式相同
    //比如加密的算法 hash的散列次数 负责shiro 会解密失败
    @Bean
    public HashedCredentialsMatcher hashedCredentialsMatcher() {
        HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
        credentialsMatcher.setHashAlgorithmName("MD5");
        credentialsMatcher.setHashIterations(10);
        return credentialsMatcher;
    }
}
